Chapter 5 CONTROL STRUCTURES THE SIMPLEST LOOP IN ADA _________________________________________________________________ We will start with the simplest loop in Ada, the ================ infinite loop which is illustrated in lines 13 LOOPDEMO.ADA through 19 of the program named LOOPDEMO.ADA. ================ The variable named Index is initialized to the value of 1 prior to entering the loop, and the loop itself is given in lines 14 through 19. The loop begins with the reserved word loop and ends with the two reserved words end loop. Any number of executable statements are placed between these two delimiters and the loop is repeated continuously until something causes the program to jump out of the loop. In this case, the variable Index is incremented each time through the loop, and when it reaches a value of 5, the exit statement is executed which causes control to jump out of the loop and begin executing instructions immediately following the end of the loop. The words exit and when are two more reserved words. The expression following the exit when reserved words must evaluate to a BOOLEAN result and when the result is TRUE, the loop is exited, but as long as the result is FALSE, the loop execution will continue. Note that the exit statement can be placed anywhere in the loop and as many conditional exits as needed can be placed within the loop. The statements illustrated in lines 21 through 27 are an alternative form of loop exit which uses the if statement which we have not yet studied. The if form of exit is such a common form of usage that it had to be included here as one of the simplest types of loops. Note that the if exit can be placed anywhere in the loop and as many as needed can be used within the loop. The if statement will be fully explained later in this chapter. THE exit STATEMENT _________________________________________________________________ There is a subtle difference between the exit in line 18 and the exit in line 26. The exit in line 18 is conditional because it is only executed if the condition evaluates to TRUE. The exit in line 26 however, is unconditional since the exit will be taken anytime control reaches the word exit. Keep in mind that an exit is used only to exit a loop, it is not used for any other construct in Ada. Page 5-1 Chapter 5 - Control Structures THE while LOOP _________________________________________________________________ The while loop is identical to the simple loop except for the addition of a test prior to the reserved word loop. The test is done at the beginning of the loop so it is slightly less general than the simple loop, but it also requires a BOOLEAN expression as part of the construct. This loop is illustrated in lines 30 to 34 of the present program. In line 30, "while Count < 5" is called the iteration clause. THE for LOOP _________________________________________________________________ The loops studied so far in this example program use an indeterminate number of passes since they calculate their own limits as they progress through the loop. It is important to point out that the BOOLEAN expressions are evaluated on every pass through the loop. The for loop, however, has its limits evaluated one time and the number of passes through the loop is completely defined before the first pass through the loop is begun. The for loop is illustrated in lines 36 to 39 where the control consists of a few words prior to the reserved word loop. In this case the loop control is the variable Index and the range of the variable is 1 through 4. The loop will be executed four times, each time with a larger number for the variable Index, since the loop index is always incremented by one. There is no provision for an increment of any other value in Ada. The reserved words for and in are used in the manner shown for all for loops. They serve to bracket the loop index, in this case named Index, and the range of the index, in this case 1 through 4 inclusive. Because the type INTEGER is so commonly used for the loop index, if the type is not specifically stated, it will be defaulted to the type INTEGER. This is to make it easier to code the majority of loops. Note that the loop parameters do not need to be of type INTEGER, but the loop index and both range limits must be of the same type. Note also that the value of the loop iterator is not available after loop termination. The loop iterator ceases to exist completely when the loop is completed. (There is good reason for this as we will see when we complete our study of the next example program.) THE BACKWARDS for LOOP _________________________________________________________________ There is a slight variation to the for loop as illustrated in lines 41 through 44, where the loop index is decremented on each pass through the logic. The word reverse is another reserved word and Page 5-2 Chapter 5 - Control Structures serves to indicate the backward counting nature of this loop. Note that the range is expressed in ascending order, but the actual execution begins at 8 and decrements by 1 on each pass until it reaches 5, where it quits after the pass through the loop with Count set to 5. THE EMPTY LOOP _________________________________________________________________ Continuing in the program named LOOPDEMO.ADA, the loop in lines 46 to 48 is given to illustrate that it is possible to write a loop that does absolutely nothing. It may seem like a silly thing to do, but there are cases, when using tasking, that it is necessary to do nothing in a loop. It is of more importance at this point to illustrate that Ada is so picky, you are not allowed to write an empty loop, but are required to inform the compiler that you really did mean for the loop to be empty by including the reserved word null within the loop. One other point must be made before we leave this program. Everything from line 14 through line 19 comprises a single Ada statement, by definition. It is definitely a complex statement, but for purposes of discussion, it is one Ada statement. Likewise, lines 22 through 27 constitute a single Ada statement, as do lines 30 through 34. This is an important concept to understand because of the block nature of Ada and we will have more to say about it later. Be sure to compile and execute this program and be sure you understand exactly what each loop does. SLIGHTLY MORE COMPLEX for STATEMENTS _________________________________________________________________ Examine the program named MORELOOP.ADA for a ================ few examples of more complex but much more MORELOOP.ADA versatile for loops. The loops illustrate a few ================ of the flexibilities designed into Ada to allow for more efficient programming. The first example has two new concepts, the first being that the loop variable, Index, is not declared in the definition part of the program, and secondly the range is defined by a type rather than variable or constant limits. Considering the first point, the loop index in a for loop does not require explicit declaration, but will be implicitly declared by the program, used during the duration of the loop, and discarded when the loop terminates. The final value of the loop index is not available for use after the loop terminates, and this is true regardless of whether the index is explicitly or implicitly declared. (We will see shortly that it is always implicitly declared by the Ada system.) The Ada language designers gave Page 5-3 Chapter 5 - Control Structures compiler writers freedom on how and when the loop index is incremented rather than dictating what the final value would be. It is a simple rule to remember that you can not depend on having the final value of the loop index when you terminate the loop. If you need the final value, you must copy it into some other variable. THE LOOP INDEX AND LIMITS MUST AGREE IN TYPE _________________________________________________________________ The second point brought out above is the fact that the loop range is given as a type. The type given, MY_TYPE, has a defined range of 10..13, so it should be no real problem seeing what the loop index range is. Moreover, since the type of the individual values of MY_TYPE are of the type universal_integer, the implicit loop index, named Index, will also be of type universal_integer. Ada will pick the correct types for you. A final point about the first loop in this program must be made. The loop index in this for loop, as well as in any for loop, will be treated as a constant within the loop, so you cannot assign a new value to it. The looping mechanism itself will be the only way that the loop index can be changed in value. OUR FIRST ATTRIBUTES IN USE _________________________________________________________________ In chapter 3, we took a brief look at attributes, but didn't really look at uses for them. In the loop in lines 30 through 34, we have the range once again defined as the limits of the type named MY_TYPE but this time we explicitly name the first and last values of the type by using the attributes. The method depicted in line 24 is more concise, but both methods lead to the same result. If you wanted to loop from the first element to some midpoint, for example, the second method gives you a way to use one of the endpoints of the range. A point that should be mentioned again is the fact that the contents of lines 24 through 28 constitute a single Ada statement, as do the contents of lines 30 through 34 inclusive. CALCULATED LOOP RANGE LIMITS _________________________________________________________________ The loop in lines 36 through 40 has range limits that are not static but that are calculated when the loop is entered. In this case, the calculations are all based on constants, but they could be based on variables of any arbitrary degree of complexity. If Page 5-4 Chapter 5 - Control Structures they are based on one or more variables, there is a subtle point that you must understand. If one or more of the variables are changed within the loop, the range does not change accordingly, because the loop range limits are calculated only once, and it occurs when the loop is entered. It should be clear that the loop range is 2 through 5 for this particular loop. A DOUBLY NESTED for LOOP _________________________________________________________________ Lines 42 through 52 contain two nested for loops with an addition to the outer loop. The identifier Named_Loop is a loop name which applies to the outer loop. Notice that the name also follows the corresponding end loop for that loop, resulting in a named loop. In lines 45 and 46 we have a conditional statement that says if the product of the Height and the Width are equal to 12, we are to exit the loop that is named Named_Loop. Without the name given we would only exit the loop currently in effect, the inner one defined by the loop index Width, but since we mention the name, we exit the loop with the given name, and exit both loops. By adding a name to a loop, you can exit out of as many nested levels as you desire with a single exit statement. Once again, according to the definition of Ada, lines 42 through 52 constitute a single statement, and lines 44 through 51 also constitute a single Ada statement, although it is embedded within the outer statement. To continue, each of lines 48, 49, and 50 constitute a single Ada statement, and each of these are embedded within both of the outer statements. Recall that each Ada statement is supposed to terminate with a semicolon, then go back and reread this paragraph with that in mind. A CLOSE LOOK AT THE LOOP INDEX _________________________________________________________________ In line 54, we assign the value of 157 to the variable named Special_Index and use that variable name for the loop index for the following loop. After the loop is terminated, we display the value of the variable to see what the final value is, and when we run the program we find that the value did not change from that assigned, namely 157. This would suggest that even if we think we are explicitly defining the loop index variable, the system is actually making up an entirely new variable, using it, and throwing it away after the loop is terminated. Ada defines a loop variable as an automatic variable which is generated when needed and discarded when it is no longer needed. More will be said about automatic variables later. The important point to grasp from this is that Ada actually implicitly declares all loop variables for us. Page 5-5 Chapter 5 - Control Structures LOOPS ARE IMPORTANT _________________________________________________________________ You will have many opportunities to use all three forms of the loops discussed here, so it would pay you to study these loops until you are sure of what they are doing. Note the similarity of the three loops, and the fact that each is a complete Ada statement terminated with a semicolon. When we study the next two controls, you will see that they are very similar, and fit the same pattern. loop <...> end loop; while loop <...> end loop; for in loop <...> end loop; Compile and execute this program taking care to observe the value of the variable named Special_Index when the loop is complete. NOW FOR CONDITIONAL STATEMENTS _________________________________________________________________ We will spend some time now examining the ================ program named IFDEMO.ADA and studying the IFDEMO.ADA conditional statements. Notice here, that we ================ don't even try to define any variables, but we will let the system generate them for us as implicit loop indices. The Ada statement contained in lines 11 through 21 is a for loop which we are now familiar with so we will use it to study how the if statement works. Notice that we display the value of Index, then use it in the first if statement in lines 14 through 16. This statement says that if the value stored in Index is less than 4, then execute the statements between the reserved words then and end if. In this case, we display the message in line 15 on the monitor. If the value stored in Index is not less than 4, we ignore the statement between the reserved words and go directly to line 17, where we encounter another if statement. This one displays a different line on the monitor if the value stored in Index is greater than 5. This is the simplest kind of if statement, and you will find it to be extremely useful, in fact, you used it in the previous two example programs. Moving ahead to the next loop, the one in lines 24 through 32, we find a more elaborate conditional, the if then else statement. In this case, if the value of Index is less than 15, one message is displayed and if not, a different message is displayed. In the prior loop, we used an if statement where a message may or may not have been displayed, but in this one, we use an if statement where one of the messages will be displayed every time. This, of course, is very similar to other programming languages. Page 5-6 Chapter 5 - Control Structures NOW FOR THE MULTIWAY if STATEMENT _________________________________________________________________ The loop in the statement contained in lines 35 through 47 is a bit more involved since there are several possibilities for selection of the line to be displayed. The word elsif is another reserved word. In this case, one and only one of the statements will be executed during each pass through the loop. The reserved word else is optional, and if it were not there, it would be possible that none of the conditions would be met and therefore none of the messages would be output. As many statements as desired can be placed between each of the reserved words such that a selection could cause a large number of statements to be executed sequentially. The last statement, given in lines 54 through 70, gives an illustration of nesting of loop and if statements. It should cause you no difficulty to understand the nesting and when you compile and run this program, you should have a good understanding of the output. THE MULTIWAY CONDITIONAL CONSTRUCT _________________________________________________________________ Examine the program named CASEDEMO.ADA for an ================ example of a program with a case statement, the CASEDEMO.ADA multiway conditional statement in Ada. Lines 11 ================ through 23 comprise a loop with a case statement contained in it. Lines 15 through 21 contain the actual case statement. The variable How_Many is the case selector variable and each time we pass through the loop, we enter the case statement with a different value stored in the variable How_Many. When How_Many has the value of 4 through 6, we select the first path, and that path only, when it has the value of 7 or 9, we select the second path, etc. The vertical bar is the or operator here, and means if we have either of these cases, do this list of statements. The case statement is composed of the reserved words case, is, when, and end case in the manner shown. All cases must be accounted for in some way since it is an error to enter the case with a value of the case selector variable for which there is not something defined for it to do. WHAT IS THE => OPERATOR? _________________________________________________________________ The "=>" operator is used in many places in an Ada program which we will see as we progress through this tutorial. It can be loosely defined as a "do this" operator, because in most places it can be read as "do this". For example in line 16, the line can be read "when How_Many is 4 through 6 do this Put statement". Page 5-7 Chapter 5 - Control Structures A special case is provided which is the others case. It is optional, but if it is included, it must be the last one listed. This is illustrated in the other example in this program, the example in lines 30 through 40. This program is an illustration of more complex operations in each of the case branches, and it is expected that you should have no difficulty discerning the operation of each of the cases. This is one of the places where a null statement can be very useful as in line 38 where we really want to do nothing and can explicitly tell the compiler so. Be sure to compile and execute this program after you are sure you understand it. The case statement occurs rather infrequently in programming, but you will use it, so you should understand it thoroughly. This would be a good time to repeat a list which was given earlier in this chapter with the if and case statements added to illustrate the symmetry of the control structures and how well thought out they really are. loop <...> end loop; while loop <...> end loop; for in loop <...> end loop; if then <...> end if; case is <...> end case; THE EVIL GOTO STATEMENT _________________________________________________________________ The program named GOTODEMO.ADA illustrates use ================ of the goto statement, a statement that has GOTODEMO.ADA fallen into ill repute among software engineers ================ in recent years. This is because the goto can be used very abusively, leading to nearly unreadable spaghetti code. There may be instances when use of the goto statement will result in very clear code, and when those cases arise, it should be used. It has been proven that it is possible to write any logic without resorting to the goto statement by using only iteration (looping), conditional branching, and sequential statements and every effort should be made to rely on only these three elements. When Ada was being developed, the developers considered leaving the goto statement completely out of the language, but it was included for a very nebulous reason. It was felt that after Ada became a popular language, there would be a need to translate existing programs from older languages, such as FORTRAN, into Ada using automatic translators. Such a job would be impossible without the goto statement, so it was included in the Ada language. Modula-2 is an example of a language structured very much like Ada, but without a goto statement defined as part of the language. Page 5-8 Chapter 5 - Control Structures The goto is available as a part of the Ada language and is illustrated in the present example program. It should be no surprise to you that goto is another reserved word. The rather messy looking double "<<" and ">>" enclose the label to which you wish to jump and the rest should be easy for you to discern. Be sure to compile and run this program. FINALLY, A USEFUL PROGRAM _________________________________________________________________ Examine the program named TEMPCONV.ADA for an ================ example of a program that really does do TEMPCONV.ADA something useful, it generates a table of ================ Centigrade to Fahrenheit temperature conversions, and it outputs a special message at the freezing point of water and another at the boiling point of water. Notice the program definition in the header that defines exactly what it does. You should have no trouble understanding every detail of this program, except of course for the rather cryptic code in lines 8, 9, 13, and 14. Although we have had a brief introduction to these, we will cover the details of them later in this tutorial. POOR CHOICE OF VARIABLE NAMES _________________________________________________________________ Compile and run TEMPCONV.ADA, then examine the ================ program named DUMBCONV.ADA for an example that DUMBCONV.ADA uses some poor choices of variable names and ================ omits the comments. This program is the same program that you just studied because it does exactly the same thing, but I am sure you will find it a little harder to follow since the names are not very useful in helping you understand what it is doing. In the beginning of this tutorial, we studied a program named UGLYFORM.ADA which was absolutely ridiculous in style. No serious programmer would write such a program as that, but many programmers seem to be happy using a style similar to the present example. You should begin, even at this early point in your Ada programming development, to develop good formatting skills. Remember that Ada was designed to be written once and read many times, so the extra time spent keying in long, meaningful identifiers will be worth it to your colleagues when they find a need to study your code. Page 5-9 Chapter 5 - Control Structures PROGRAMMING EXERCISES _________________________________________________________________ 1. Write a program with looping and conditional statements that will output the year and your age during each year from the time you were born until you were 21. Include a special note the year you started school and another note the year you graduated from High School. Example output follows; In 1938, I was 0 years old. In 1939, I was 1 years old. ... ... In 1943, I was 5 years old, and started School. ... etc. 2. Rewrite exercise 1 using a case statement. Page 5-10